<?php
/**
 * 适配器模式
 * User: Yan
 * Date: 2018/7/5
 * Time: 14:54
 */

namespace Yan;

/**
 * 适配器可能出现场景之一： 我们公司现在使用了A公司的接口来获取用户所在位置的天气信息，但是现在需要切换成B公司的接口。两个公司的接口格式并不一样。
 * @package Yan
 */

class My
{
    public function getWeather($ip = '127.0.0.1')
    {
        # 我们的业务逻辑  需要在这里获取用户所在位置的天气信息
        $class       = new AClass();
        $weatherInfo = $class->get($ip);  // A公司使用IP来获取天气信息
        echo $weatherInfo;
    }

    public function getWeather2()
    {
        # B公司的接口 但是所需要的是地区的文字 不是ip
        $class       = new BClass();
        $weatherInfo = $class->getWeatherInfo('广东');
        echo $weatherInfo;
    }

}

# 这种情况下 我们可以使用适配器模式，新建适配器接口、不同的适配器类
interface IAdapter
{
    public function getWeather($ip);
}

# A公司的适配器实现
class AAdapter implements IAdapter
{
    public function getWeather($ip)
    {
        $class       = new AClass();
        $weatherInfo = $class->get($ip);  // A公司使用IP来获取天气信息
        return $weatherInfo;
    }
}

# B公司的适配器实现
class BAdapter implements IAdapter
{
    public function getWeather($ip)
    {
        $class = new BClass();
        # 先使用ip获取地区的文字
        $tmp         = $class->ip2name($ip);
        $weatherInfo = $class->getWeatherInfo($tmp);  // B公司使用地区文字来获取天气信息
        return $weatherInfo;
    }
}

# 到现在为止的使用还是要如下代码
/*
# 使用A公司的接口
$class = new AAdapter();
echo $class->getWeather($ip);

# 使用B公司的接口
$class = new BAdapter();
echo $class->getWeather($ip);
 */

# 如果要切换 还是需要修改很多地方，这个使用我们可以使用工厂模式来得到对象。如果需要切换不同公司的接口，只需要在工厂方法中切换，不需要修改主代码的类
# 如果不这样的缺点：如果使用的地方多，需要每个地方都new出B公司的类，并且要添加一句ip转换地区文字的代码
# 使用后：只需要添加不同的适配器，并且在工厂中修改为B适配器。
# 适配器的总结：将不同的逻辑封装成统一格式的对外接口，可以在不修改主代码的情况下扩展或者切换不同接口。场景之二：Mysql函数和Mysqli函数、PDO的灵活切换
/*
$class = Factory::getClass('weather');
echo $class->getWeather($ip);
 */